﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

namespace OscGitEmptyFolderHandler
{
    public partial class HandlerRun : Form
    {


        public HandlerRun()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            RegistryKey reg = Registry.CurrentUser.CreateSubKey("SoftWare\\OscGitEmptyFolderHandler");
            if (reg != null && reg.GetValue("DefaultFolderPath") != null)
            {
                folderDlgSvnRoot.SelectedPath = reg.GetValue("DefaultFolderPath").ToString();
                lblClickToSelectFolder.Text = reg.GetValue("DefaultFolderPath").ToString();
            }
        }

        private void lblClickToSelectFolder_Click(object sender, EventArgs e)
        {
            if (folderDlgSvnRoot.ShowDialog() == DialogResult.OK)
            {
                lblClickToSelectFolder.Text = folderDlgSvnRoot.SelectedPath;
            }
        }

        private void btnCreateFile_Click(object sender, EventArgs e)
        {
            if (folderDlgSvnRoot.SelectedPath == "")
            {
                MessageBox.Show(@"请先选择Svn的根目录");
                return;
            }
            var handler = new Handler(folderDlgSvnRoot.SelectedPath,chkHideFile.Checked);
            handler.Run();
            RunResult.Text = string.Format("执行成功：共找到 {0} 个空文件夹",handler.FoldersCount);
        }

        /// <summary>
        /// 多线程版本
        /// </summary>
        private class Handler
        {
            public Handler(string rootFolderAbsolutePath,bool hideFile)
            {
                this._rootFolderAbsolutePath = rootFolderAbsolutePath;
                this._hideFile = hideFile;
            }

            public int FoldersCount { get;private set; }//读取到的空目录个数

            private readonly string _rootFolderAbsolutePath;//刚开始的根目录
            private readonly List<string> _tasks = new List<string>();//任务列表，即文件夹列表
            private readonly ManualResetEvent _hasNew = new ManualResetEvent(false);// 用于通知是否有新任务的“信号器”
            private readonly bool _hideFile;

            public void Run()
            {
                var th = new Thread(CreateFile) {IsBackground = true};
                th.Start();
                EachFolder(_rootFolderAbsolutePath);
            }

            private void EachFolder(object absolutePath)
            {
                string path = absolutePath.ToString();
                string[] subFolders = Directory.GetDirectories(path);//当前文件夹的子文件夹列表
                string[] files = Directory.GetFiles(path);//当前文件夹内的文件列表
                if (subFolders.Length + files.Length == 0)
                {
                    lock (_tasks)
                    {
                        FoldersCount++;
                        _tasks.Add(path);
                        _hasNew.Set();
                    }
                }
                foreach (string folder in subFolders)
                {
                    EachFolder(folder);
                }
            }

            private void CreateFile()
            {
                while (true)
                {
                    // 等待接收信号，阻塞线程。
                    _hasNew.WaitOne();

                    // 接收到信号后，重置“信号器”，信号关闭。
                    _hasNew.Reset();

                    // 由于队列中的任务可能在极速地增加，这里等待是为了一次能处理更多的任务，减少对队列的频繁“进出”操作。
                    Thread.Sleep(50);

                    // 开始执行队列中的任务。
                    // 由于执行过程中还可能会有新的任务，所以不能直接对原来的进行操作，
                    // 先将任务复制一份后将其清空，然后对这份拷贝进行操作。
                    List<string> tasksCopy;
                    lock (_tasks)
                    {
                        tasksCopy = new List<string>(_tasks.ToArray());
                        _tasks.Clear();
                    }

                    foreach (var task in tasksCopy)
                    {
                        string filePath = task + (task.EndsWith("/") ? "" : "/") + "SvnEmptyFolder.txt";
                        File.Create(filePath).Close();
                        if (_hideFile)
                        {
                            File.SetAttributes(filePath, FileAttributes.Hidden);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 单线程版本
        /// </summary>
        /// <param name="absolutePath"></param>
        private void HandleEmptyFolder(object absolutePath)
        {
            string absPath = absolutePath.ToString();//当前文件夹绝对路径
            string[] subFolders = Directory.GetDirectories(absPath);//当前文件夹的子文件夹列表
            string[] files = Directory.GetFiles(absPath);//当前文件夹内的文件列表
            if (subFolders.Length + files.Length == 0)
            {
                File.Create(absPath + (absPath.EndsWith("/") ? "" : "/") + "SvnEmptyFolder.txt").Close();
                
            }
            foreach (string folder in subFolders)
            {
                HandleEmptyFolder(folder);
            }
        }

        private void HandlerRun_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (folderDlgSvnRoot.SelectedPath != "")
            {
                RegistryKey reg = Registry.CurrentUser.CreateSubKey("SoftWare\\OscGitEmptyFolderHandler");
                if(reg!=null)
                    reg.SetValue("DefaultFolderPath", folderDlgSvnRoot.SelectedPath);
            }
        }
    }
}
